package main

import (
	"fmt"
	"log"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var db *gorm.DB

func init() {
	var err error
	dsn := "vic:vic@/test?parseTime=true"
	mysqlDialector := mysql.Open(dsn)

	db, err = gorm.Open(mysqlDialector, &gorm.Config{
		Logger: logger.Default.LogMode(logger.Info),
	})
	if err != nil {
		log.Fatal(err, "!!!")
	}
	fmt.Println(db)
	db = db.Debug()
}

type Student struct {
	Id       int    // `gorm:"primaryKey"`
	Name     string `gorm:"type:varchar(48)"`
	Age      int    `gorm:"type:tinyint"`
	Birthday *time.Time
	Gender   byte `gorm:"size:8"`
}

func (Emp) TableName() string {
	return "employees"
}

// func (s *Student) String() string {
// 	return fmt.Sprintf("<Student id:%d, %s, %d>", s.ID, s.Name, s.Age)
// }

type Emp struct {
	EmpNo     int `gorm:"primaryKey"`
	FirstName string
	//Fn string `gorm:"column:first_name"`
	LastName  string
	BirthDate string
	Hire_date string
	Gender    byte
}

func main() {
	//delete
	db.
		Delete(&Student{Id: 1})
	//update
	// var s Student
	// fmt.Println(s)
	// db.Take(&s, 103)
	// fmt.Println(s)
	// if s.Id > 0 {
	// 	s.Name = "John"
	// 	s.Age += 10
	// }
	// fmt.Println(s)
	// db.Save(&s)
	// fmt.Println(s)

	// db.Model(&Student{}).
	// 	Where("id > 101").
	// 	//Update("age", 44)
	// 	//Updates(&Student{Name: "vic", Age: 51})
	// 	Updates(map[string]any{"name": "sammy", "age": 35})

	// fmt.Println(db.Error)
	// fmt.Println(db.RowsAffected)
	// // Left Join
	// type Result struct {
	// 	Emp    // 嵌套
	// 	Salary int
	// }
	// var rs []*Result
	// db.Select("e.*, s.salary").Table("employees as e").
	// 	Joins("left join salaries as s on e.emp_no = s.emp_no").
	// 	Scan(&rs)
	// fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~~~")
	// for _, v := range rs {
	// 	fmt.Println(v)
	// }
	// Join
	// type Result struct {
	// 	EmpNo     int
	// 	FirstName string
	// 	LastName  string
	// 	Salary    int
	// }
	// var rs []*Result
	// db.Select("e.emp_no, e.first_name, e.last_name", "s.salary").Table("employees as e").Joins("join salaries as s on e.emp_no = s.emp_no").Scan(&rs)
	// for _, v := range rs {

	// 	fmt.Println(v, "##")
	// }
	// fmt.Println(len(rs))
	// // type Result struct {
	// 	Name string
	// 	C    int
	// }
	// var rows []*Result
	// db.Select("name", "count(id) as c").Group("name").
	// 	//Table("students").
	// 	Model(&Student{}).
	// 	//	Find(&rows)
	// 	Scan(&rows)

	// if db.Error != nil {
	// 	log.Fatal(db.Error, "#####")
	// }
	// fmt.Println(rows)
	// for _, v := range rows {
	// 	fmt.Println(v)
	// }

	//var students []*Result
	//	var students []*Student
	//db.Find(&students)
	// db.Distinct("Name", "id").Find(&students)
	// db.Select("Name", "id").Find(&students)
	// db.Select([]string{"id, name"}).Find(&students)
	// db.Select([]string{"id, name"}).Limit(2).Offset(3).Find(&students)
	// rows, err := db.
	// 	Table("students").
	// 	Select("name", "count(id) as c").
	// 	Group("name").
	// 	// Where(
	// 	// 	//"name = ? and id=?", "vic", 1,
	// 	// 	//map[string]interface{}{"id": 1, "name": "vic"},
	// 	// 	//&Student{ID: 100},
	// 	// 	"id >=101",
	// 	// ).
	// 	// //Or("id = 104").
	// 	//Order("name, id desc").
	// 	//Find(&students)
	// 	Rows()

	// if err != nil {
	// 	log.Fatal(err)
	// }
	// for rows.Next() {

	// 	var r Result
	// 	err = rows.Scan(&r.name, &r.c)
	// 	if err != nil {
	// 		fmt.Println(err, "$$$$")
	// 		continue
	// 	}
	// 	fmt.Println(r)
	// }
	// if db.Error != nil {
	// 	log.Fatal(db.Error)
	// }
	// fmt.Println(students)
	// // var s Student
	// //db := db.Last(&s)
	// db := db.Take(&s)
	// if db.Error != nil {
	// 	log.Fatal(db.Error)
	// }

	// fmt.Println(s)
	// s = Student{}
	// db = db.Take(&s, 105)
	// if db.Error != nil {
	// 	log.Fatal(db.Error)
	// }
	// fmt.Println(s)

	//s1 := Student{Name: "vic"}
	// t1 := time.Now()
	// t2, _ := time.Parse("2006/1/2", "2010/03/15")
	// s2 := Student{Name: "Jerry", Birthday: &t1}
	// s3 := Student{Name: "Ben", Birthday: &t2}
	// //r := db.Create(&s1)
	// r := db.Create([]*Student{&s2, &s3})
	// fmt.Println(s2, s3, "###")
	// if r.Error != nil {
	// 	log.Fatal(r.Error)
	// }
	// fmt.Println(s2, s3, "%%%")

	// db.Migrator().DropTable(&Student{})
	// db.Migrator().CreateTable(&Student{})

	// var instance Emp
	// result := db.Take(&instance)
	// fmt.Println(result.Error, result.Error == nil)
	// fmt.Println(instance)
}
